﻿using Gargoyle.Roton;
using Gargoyle.ZZT;
using OpenTK;
using OpenTK.Input;
using OpenTK.Graphics.OpenGL;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Lyon
{
    /// <summary>
    /// Runs Lyon using a framebuffer-based OpenGL window.
    /// </summary>
    class OpenGLFBWindow : OpenGLWindow
    {
        private int LastTexture = -1;

        public OpenGLFBWindow() : base() { }
        public OpenGLFBWindow(decimal Scale) : base(Scale) { }

        protected override void DoGLInit()
        {
            GL.Enable(EnableCap.Texture2D);
        }

        protected override void DoRender(FrameEventArgs e)
        {
            // generate texture
            Bitmap Framebuffer = Video.Bitmap;
            BitmapData FBData = Framebuffer.LockBits(new System.Drawing.Rectangle(0, 0, Framebuffer.Width, Framebuffer.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            int FBTexture = GL.GenTexture();
            GL.BindTexture(TextureTarget.Texture2D, FBTexture);
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Framebuffer.Width, Framebuffer.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, FBData.Scan0);
            Framebuffer.UnlockBits(FBData);
            if(VideoSmoothing)
            {
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
            }
            else
            {
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
            }

            // delete old texture reference
            if(LastTexture != -1)
                GL.DeleteTexture(LastTexture);
            LastTexture = FBTexture;

            // draw large quad with the framebuffer texture on it
            GL.Begin(BeginMode.Quads);
            GL.TexCoord2(0.0f, 0.0f); GL.Vertex2(0, 0);
            GL.TexCoord2(1.0f, 0.0f); GL.Vertex2(GameWidth, 0);
            GL.TexCoord2(1.0f, 1.0f); GL.Vertex2(GameWidth, GameHeight);
            GL.TexCoord2(0.0f, 1.0f); GL.Vertex2(0, GameHeight);
            GL.End();
        }

        protected override void DoUnload()
        {
            if(Initialized)
                GL.DeleteTexture(LastTexture);
        }
    }
}
